package org.eclipse.emf.db.tests.core;

import static org.junit.Assert.assertTrue;

import java.sql.SQLException;

import org.eclipse.emf.db.DBObject;
import org.eclipse.emf.db.impl.DBObjectImpl;
import org.eclipse.emf.db.tests.model.Child;
import org.eclipse.emf.db.tests.model.ModelFactory;
import org.eclipse.emf.db.tests.model.ModelPackage;
import org.eclipse.emf.db.tests.model.Root;
import org.eclipse.emf.db.tests.model.SubRoot;
import org.eclipse.emf.db.util.DBUtil;
import org.junit.Test;

public class TestReloadReference {
    @Test
    public void reload_01_0n_add() throws SQLException {
        Root root=ModelFactory.eINSTANCE.createRoot();
        Child child1=ModelFactory.eINSTANCE.createChild();
        root.getChildren().add(child1);
        DBUtil.reload(root, ModelPackage.eINSTANCE.getRoot_Children());
        assertTrue(root.getChildren().isEmpty());
    }

    @Test
    public void reload_01_0n_remove() throws SQLException {
        Root root=ModelFactory.eINSTANCE.createRoot();
        Child child1=ModelFactory.eINSTANCE.createChild();
        root.getChildren().add(child1);
        cleanState(root, child1);
        root.getChildren().remove(child1);
        assertTrue("DBDETACHED IS WRONG", root.dbDetached(ModelPackage.eINSTANCE.getRoot_Children(), DBObject.class).iterator().hasNext());
        DBUtil.reload(root, ModelPackage.eINSTANCE.getRoot_Children());
        assertTrue(!root.getChildren().isEmpty());
    }

    /**
     * Hack to 'simulate' a save
     */
    private void cleanState(DBObject... objects) {
        for (DBObject obj : objects) {
            ((DBObjectImpl) obj).dbClearModified();
            ((DBObjectImpl) obj).dbClearDetached();
        }
    }

    @Test
    public void reload_0n_01_add() throws SQLException {
        Root root=ModelFactory.eINSTANCE.createRoot();
        Child child1=ModelFactory.eINSTANCE.createChild();
        root.getChildren().add(child1);
        DBUtil.reload(child1, ModelPackage.eINSTANCE.getChild_Root());
        assertTrue(root.getChildren().isEmpty());
    }

    @Test
    public void reload_0n_01_remove() throws SQLException {
        Root root=ModelFactory.eINSTANCE.createRoot();
        Child child1=ModelFactory.eINSTANCE.createChild();
        root.getChildren().add(child1);
        cleanState(root, child1);
        root.getChildren().remove(child1);
        DBUtil.reload(child1, ModelPackage.eINSTANCE.getChild_Root());
        assertTrue(!root.getChildren().isEmpty());
    }

    @Test
    public void reload_01_01_add() throws SQLException {
        Root root=ModelFactory.eINSTANCE.createRoot();
        SubRoot subRoot=ModelFactory.eINSTANCE.createSubRoot();
        root.setSubRoot(subRoot);
        DBUtil.reload(root, ModelPackage.eINSTANCE.getRoot_SubRoot());
        assertTrue(root.getSubRoot() == null);
        assertTrue(subRoot.getRoot() == null);
    }

    @Test
    public void reload_01_01_add_inverted() throws SQLException {
        Root root=ModelFactory.eINSTANCE.createRoot();
        SubRoot subRoot=ModelFactory.eINSTANCE.createSubRoot();
        root.setSubRoot(subRoot);
        DBUtil.reload(subRoot, ModelPackage.eINSTANCE.getSubRoot_Root());
        assertTrue(root.getSubRoot() == null);
        assertTrue(subRoot.getRoot() == null);
    }

    @Test
    public void reload_01_01_remove() throws SQLException {
        Root root=ModelFactory.eINSTANCE.createRoot();
        SubRoot subRoot=ModelFactory.eINSTANCE.createSubRoot();
        root.setSubRoot(subRoot);
        cleanState(root, subRoot);
        root.setSubRoot(null);
        DBUtil.reload(root, ModelPackage.eINSTANCE.getRoot_SubRoot());
        assertTrue(root.getSubRoot() != null);
        assertTrue(subRoot.getRoot() != null);
    }

    @Test
    public void reload_01_01_remove_inverted() throws SQLException {
        Root root=ModelFactory.eINSTANCE.createRoot();
        SubRoot subRoot=ModelFactory.eINSTANCE.createSubRoot();
        root.setSubRoot(subRoot);
        cleanState(root, subRoot);
        root.setSubRoot(null);

        DBUtil.reload(subRoot, ModelPackage.eINSTANCE.getSubRoot_Root());
        assertTrue(subRoot.getRoot() != null);
        assertTrue(root.getSubRoot() != null);
    }
}
